﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using _PLATFORM.DATA;
using _PLATFORM.DATA.Custom_Classes;

namespace _PLATFORM.WEB.Controllers
{ 
    [Authorize(Roles = "Administrator, Reseller")]
    public class ComponentController : Controller
    {
        private eCommPlatformRepoEntities db = new eCommPlatformRepoEntities();
        
        private static string   ProductType { get; set; }
        private static Guid?     UserID      { get; set; }

        //
        // GET: /Component/

        public ViewResult Index(string productType)
        {
            ProductType = productType;

            ViewBag.ProductType = ProductType;

            //MembershipUser currentUser = Membership.GetUser(User.Identity.Name);

            // Get User ID
            Guid userID = DATA.Custom_Classes.User.UserID;

            // Set User ID
            UserID = userID;

            var queryResults = db.Get_Products_By_Type_For_Users(productType, userID).ToList();

            if (DATA.Custom_Classes.User.UseParentInventory)
            {
                queryResults.AddRange(db.Get_Products_By_Type_For_Users(productType, DATA.Custom_Classes.User.ParentID).ToList());
            }
            
            var products = new List<PRODUCT>();
            
            var productCategories = new List<List<ProductCategory>>();

            var hasProducts = false;
            
            foreach (var result in queryResults)
            {
                hasProducts = true;
                var thisProductCategories = new List<ProductCategory>();

                var product = new PRODUCT
                                 {
                                     PRODUCT_ID = result.PRODUCT_ID,
                                     NAME = result.NAME,
                                     COST = result.COST,
                                     PRICE = result.PRICE,
                                     PART_NUMBER = result.PART_NUMBER.ToString(),
                                     LEAD_TIME = result.LEAD_TIME,
                                     INVENTORY = result.INVENTORY,
                                     IMAGE = result.IMAGE,
                                     PDF = result.PDF,
                                     DESCRIPTION = result.DESCRIPTION,
                                     STATISTICS = result.STATISTICS,
                                     SUPPLIER_NAME = result.SUPPLIER_NAME,
                                     SUPPLIER_ID = result.SUPPLIER_ID
                                 };

                if (productType == "Component")
                {
                
                    #region Get Product Associated Data
                
                    // Get the Fitting Types for this product
                    // (i.e., Transport Types, Product Types, Unloading Types, ...
                    var associatesQuery = db.Get_Product_Fitting_Types_And_Associated_Assets(result.PRODUCT_ID);

                    decimal currentTypeID = 99;
                    var resultRowsCounter = 0;

                    var pc = new ProductCategory();
                    var ca = new CategoryAsset();
                    var assetName = "";
                    foreach (var associate in associatesQuery)
                    {
                        assetName = associate.ASSET_NAME;

                        ca = new CategoryAsset();

                        if (resultRowsCounter != 0)
                        {
                            if (currentTypeID != Decimal.Parse(associate.FITTING_TYPE_ID.ToString()))
                            {
                                thisProductCategories.Add(pc);
                                currentTypeID = Decimal.Parse(associate.FITTING_TYPE_ID.ToString());
                                pc = new ProductCategory();
                                pc.ProductID = result.PRODUCT_ID;
                                pc.Items = new List<CategoryAsset>();
                                pc.Name = associate.CATEGORY;
                                ca = new CategoryAsset { Name = assetName };
                                pc.Items.Add(ca);
                            }
                            else
                            {
                                // Add the items to the category
                                ca = new CategoryAsset { Name = assetName };
                                pc.Items.Add(ca);
                            }
                        }

                        if (resultRowsCounter == 0)
                        {
                            currentTypeID = Decimal.Parse(associate.FITTING_TYPE_ID.ToString());
                            pc = new ProductCategory();
                            pc.ProductID = result.PRODUCT_ID;
                            pc.Items = new List<CategoryAsset>();
                            pc.Name = associate.CATEGORY;
                            ca = new CategoryAsset();
                            ca.Name = assetName;
                            pc.Items.Add(ca);
                        }

                        resultRowsCounter++;

                    }

                    // Add the items to the category
                    ca = new CategoryAsset { Name = assetName };
                    thisProductCategories.Add(pc);

                    // Get only unique values of Fitting Types
                    //IEnumerable<PRODUCT_FITTING_TYPE> uniqueFittingTypes = product.PRODUCT_FITTING_TYPE.Distinct();

                    #endregion

                    productCategories.Add(thisProductCategories);
                }

                // Add PRODUCT to the List of Products
                products.Add(product);
            }

            if (productType == "Component")
            {
                ViewBag.ProductCategories = productCategories as List<List<ProductCategory>>;
                EstablishFittingTypeViewBags();
            }
                

            //if (hasProducts != false)
                return View(products);
            //else
                

            // Because This User Has No Products
            //if (ProductType == "Component")
            //{
            //    EstablishFittingTypeViewBags();
            //}
            // Get All Suppliers For This Reseller
            var suppliers = db.SUPPLIERs.Where(s => s.USER_ID == DATA.Custom_Classes.User.UserID).OrderBy(s => s.NAME);
            ViewBag.SupplierSelectList = new SelectList(suppliers, "SUPPLIER_ID", "NAME");

            return View("Create");
            
        }

        //
        // GET: /Component/Details/5

        public ViewResult Details(decimal id)
        {
            ViewBag.ProductType = ProductType;

            PRODUCT product = db.PRODUCTs.Find(id);
            return View(product);
        }

        //
        // GET: /Component/Create

        public ActionResult Create(string productType)
        {
            var LTypes = new List<string> {"Days", "Weeks", "Months"};
            ViewBag.LeadTypes = new SelectList(LTypes);

            UserID = DATA.Custom_Classes.User.UserID;

            ViewBag.ProductType = productType;

            if (productType == "Component")
            {
                EstablishFittingTypeViewBags();
            }

            // Get all Suppliers
            var suppliers = db.SUPPLIERs.Where(s => s.USER_ID == UserID).OrderBy(s => s.NAME).ToList();
            ViewBag.SupplierSelectList = new SelectList(suppliers, "SUPPLIER_ID", "NAME");

            return View();
        } 

        //
        // POST: /Component/Create

        [HttpPost]
        public ActionResult Create(PRODUCT product, FormCollection collection, IEnumerable<HttpPostedFileBase> fileBase)
        {
            product.USER_ID = DATA.Custom_Classes.User.UserID;

            ViewBag.ProductType = ProductType;

            if (ProductType == "Component")
            {

                var pProdType = new PRODUCT_PRODUCT_TYPE();
                pProdType.PRODUCT_TYPE_ID = 1;
                pProdType.PRODUCT_ID = product.PRODUCT_ID;
                db.PRODUCT_PRODUCT_TYPE.Add(pProdType);

                // Get All the Fitting Types
                var fTypes = GetFittingTypes();

                // Get the products curret Fitting Type Assets
                var p_fTypes = db.PRODUCT_FITTING_TYPE_ASSET;

                #region Manage Types and Selected Type Assets

                foreach (var type in fTypes)
                {
                    // Get the selected items from the FormCollection
                    var selectedTypes = collection[type.NAME];

                    // Add associations to the ones selected
                    foreach (var selectedAssetTypeID in selectedTypes.Split(','))
                    {
                        var productFittingType = new PRODUCT_FITTING_TYPE();
                        productFittingType.PRODUCT_ID = product.PRODUCT_ID;
                        productFittingType.USER_ID = product.USER_ID;
                        productFittingType.FITTING_TYPE_ID = type.FITTING_TYPE_ID;
                        db.PRODUCT_FITTING_TYPE.Add(productFittingType);

                        var pfta = new PRODUCT_FITTING_TYPE_ASSET();
                        pfta.FITTING_TYPE_ASSET_ID = decimal.Parse(selectedAssetTypeID);
                        pfta.PRODUCT_ID = product.PRODUCT_ID;
                        pfta.PRODUCT_FITTING_TYPE_ASSET_ID = 0;
                        pfta.USER_ID = product.USER_ID;
                        db.PRODUCT_FITTING_TYPE_ASSET.Add(pfta);
                    }
                }

                #endregion

            }
            else
            {
                var pProdType = new PRODUCT_PRODUCT_TYPE();
                pProdType.PRODUCT_TYPE_ID = 2;
                pProdType.PRODUCT_ID = product.PRODUCT_ID;
                db.PRODUCT_PRODUCT_TYPE.Add(pProdType);
            }

            #region Try to save the IMAGE & PDF

            var ctr = 0;

            foreach (var files in Request.Files)
            {
                var ticks = DateTime.Now.Ticks.ToString();

                HttpPostedFileBase file = Request.Files[ctr];
                if (file.ContentLength > 0)
                {
                    var pathString = "~/Content/User/";

                    if (file.ContentType.Contains("jp") | file.ContentType.Contains("png") | file.ContentType.Contains("gif"))
                    {
                        product.IMAGE = ticks + file.FileName;
                        pathString += "Images";
                    }

                    if (file.ContentType.Contains("pdf"))
                    {
                        product.PDF = ticks + file.FileName;
                        pathString += "PDFs";
                    }

                    var savepath = Server.MapPath(Url.Content(pathString));
                    if (!Directory.Exists(savepath))
                        Directory.CreateDirectory(savepath);
                    var filePath = Path.Combine(@savepath, Path.GetFileName(ticks + file.FileName));
                    file.SaveAs(filePath);
                }
                ctr++;
            }

            #endregion

            // Find the selected SUPPLIER
            var supplier = collection["Supplier"];
            product.SUPPLIER_ID = decimal.Parse(supplier);
            product.LEAD_TIME += " " + collection["leadTypes"];

            try
            {
                if (ModelState.IsValid){
                    db.PRODUCTs.Add(product);
                    db.SaveChanges();

                    return RedirectToAction("Index", new { productType = ProductType });
                }
            }catch (DbEntityValidationException dbEx){
                foreach (var validationErrors in dbEx.EntityValidationErrors){
                    foreach (var validationError in validationErrors.ValidationErrors){
                        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    }
                }
            }

            return View(product);
        }
        
        //
        // GET: /Component/Edit/5

        List<FITTING_TYPE> fittingTypes = new List<FITTING_TYPE>();

        private List<FITTING_TYPE> GetFittingTypes()
        {
            if(fittingTypes.Count == 0)
            {
                fittingTypes = db.FITTING_TYPE.OrderBy(ft => ft.ORDER).Where(ft => ft.USER_ID == UserID).ToList();
            }

            return fittingTypes;
        }

        public ActionResult Edit(decimal id)
        {

            if (ProductType == "Component")
            {
                // Get all fitting types
                //var fitting_type_assets = db.FITTING_TYPE_ASSET.Include(f => f.FITTING_TYPE).OrderBy(f => f.FITTING_TYPE.ORDER); // Old
                var fitting_type_assets = db.FITTING_TYPE_ASSET.Where(f => f.USER_ID == DATA.Custom_Classes.User.UserID);

                ViewBag.FittingTypes = GetFittingTypes() as List<FITTING_TYPE>;

                ViewBag.FittingTypeAssetList = fitting_type_assets as IEnumerable<FITTING_TYPE_ASSET>;

                ViewBag.ProductFittingTypeAssets = db.PRODUCT_FITTING_TYPE_ASSET as IEnumerable<PRODUCT_FITTING_TYPE_ASSET>;
                
            }

            ViewBag.ProductType = ProductType;

            ViewBag.ProductID = id;

            PRODUCT product = db.PRODUCTs.Find(id);

            // Get all Suppliers
            var suppliers = db.SUPPLIERs.Where(s => s.USER_ID == UserID).OrderBy(s => s.NAME);

            //ViewBag.Suppliers = suppliers as IEnumerable<SUPPLIER>;

            // Get product supplier
            var selectedSupplier = suppliers.Where(s => s.SUPPLIER_ID == product.SUPPLIER_ID).ToList();

            //ViewBag.SelectedSupplier = selectedSupplier[0].SUPPLIER_ID;

            ViewBag.SupplierSelectList = new SelectList(suppliers, "SUPPLIER_ID", "NAME", selectedSupplier[0].SUPPLIER_ID);

            return View(product);
        }

        //
        // POST: /Component/Edit/5

        [HttpPost]
        public ActionResult Edit(PRODUCT product, FormCollection collection, IEnumerable<HttpPostedFileBase> fileBase, string c_img, string c_pdf)
        {
            product.USER_ID = DATA.Custom_Classes.User.UserID;

            if (ProductType == "Component")
            {

                // Get All the Fitting Types
                var fTypes = GetFittingTypes();

                // Get the products curret Fitting Type Assets
                var p_fTypes = db.PRODUCT_FITTING_TYPE_ASSET;

                #region Manage Types and Selected Type Assets

                foreach (var type in fTypes)
                {
                    // Get the selected items from the FormCollection
                    var selectedTypes = collection[type.NAME];

                    // Get the Current Fitting Type Assets for this Product and Fitting Type
                    var productFittingTypeAssets =
                        p_fTypes.Where(p => p.PRODUCT_ID == product.PRODUCT_ID).Where(
                            p => p.FITTING_TYPE_ASSET.FITTING_TYPE_ID == type.FITTING_TYPE_ID);

                    // Remove existing Associations
                    foreach (var productFittingTypeAsset in productFittingTypeAssets)
                    {
                        db.PRODUCT_FITTING_TYPE_ASSET.Remove(productFittingTypeAsset);
                    }
                    db.SaveChanges();

                    // Add associations to the ones selected
                    foreach (var selectedAssetTypeID in selectedTypes.Split(','))
                    {
                        var pfta = new PRODUCT_FITTING_TYPE_ASSET();
                        pfta.FITTING_TYPE_ASSET_ID = decimal.Parse(selectedAssetTypeID);
                        pfta.PRODUCT_ID = product.PRODUCT_ID;
                        pfta.PRODUCT_FITTING_TYPE_ASSET_ID = 0;
                        pfta.USER_ID = product.USER_ID;
                        db.PRODUCT_FITTING_TYPE_ASSET.Add(pfta);
                    }
                    db.SaveChanges();

                }

                #endregion
            }

            #region Try to save the IMAGE & PDF
            
            var ctr = 0;
            var imgChanged = false;
            var pdfChanged = false;

            foreach (var files in Request.Files)
            {
                var ticks = DateTime.Now.Ticks.ToString();

                HttpPostedFileBase file = Request.Files[ctr];
                if (file.ContentLength > 0)
                {
                    var pathString = "~/Content/User/";
                    
                    if (file.ContentType.Contains("jp") | file.ContentType.Contains("png") | file.ContentType.Contains("gif"))
                    {
                        product.IMAGE = ticks + file.FileName;
                        pathString += "Images";
                        imgChanged = true;
                    }

                    if (file.ContentType.Contains("pdf"))
                    {
                        product.PDF = ticks + file.FileName;
                        pathString += "PDFs";
                        pdfChanged = true;
                    }

                    var savepath = Server.MapPath(Url.Content(pathString));
                    if (!Directory.Exists(savepath))
                        Directory.CreateDirectory(savepath);
                    var filePath = Path.Combine(@savepath, Path.GetFileName(ticks + file.FileName));
                    file.SaveAs(filePath);
                }
                ctr++;
            }

            if (!imgChanged)
            {
                // Go fetch the image
                product.IMAGE = String.IsNullOrEmpty(c_img) ? null : c_img;
            }

            if (!pdfChanged)
            {
                // Go fetch the PDF
                product.PDF = String.IsNullOrEmpty(c_pdf) ? null : c_pdf;
            }

            #endregion

            // Find the selected SUPPLIER
            var supplier = collection["SupplierSelectList"];
            product.SUPPLIER_ID = decimal.Parse(supplier);

            try
            {
                db.Entry(product).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index", new {productType = ProductType});
            }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    }
                }

            }
            return View(product);
        }

        public ActionResult Duplicate(decimal id)
        {
            if (ProductType == "Component")
            {
                EstablishFittingTypeViewBags();
            }

            PRODUCT product = db.PRODUCTs.Find(id);

            // Get all Suppliers
            var suppliers = db.SUPPLIERs.Where(s => s.USER_ID == UserID).OrderBy(s => s.NAME);

            ViewBag.Suppliers = suppliers as IEnumerable<SUPPLIER>;

            // Get product supplier
            var selectedSupplier = suppliers.Where(s => s.SUPPLIER_ID == product.SUPPLIER_ID).ToList();

            ViewBag.SelectedSupplier = selectedSupplier[0].SUPPLIER_ID;

            ViewBag.ProductID = id;

            ViewBag.ProductType = ProductType;

            return View(product);
        }

        [HttpPost]
        public ActionResult Duplicate(PRODUCT product, FormCollection collection, IEnumerable<HttpPostedFileBase> fileBase, string c_img, string c_pdf)
        {
            product.PRODUCT_ID = 0;
            product.USER_ID = DATA.Custom_Classes.User.UserID;

            if (ProductType == "Component")
            {
                var pProdType = new PRODUCT_PRODUCT_TYPE();
                pProdType.PRODUCT_TYPE_ID = 1;
                pProdType.PRODUCT_ID = product.PRODUCT_ID;
                db.PRODUCT_PRODUCT_TYPE.Add(pProdType);

                // Get All the Fitting Types
                var fTypes = GetFittingTypes();

                // Get the products curret Fitting Type Assets
                var p_fTypes = db.PRODUCT_FITTING_TYPE_ASSET;

                #region Manage Types and Selected Type Assets

                foreach (var type in fTypes)
                {
                    // Get the selected items from the FormCollection
                    var selectedTypes = collection[type.NAME];

                    if (selectedTypes != null && selectedTypes.Count() != 0)
                    {
                        // Add associations to the ones selected
                        foreach (var selectedAssetTypeID in selectedTypes.Split(','))
                        {
                            var productFittingType = new PRODUCT_FITTING_TYPE();
                            productFittingType.PRODUCT_ID = product.PRODUCT_ID;
                            productFittingType.USER_ID = product.USER_ID;
                            productFittingType.FITTING_TYPE_ID = type.FITTING_TYPE_ID;
                            db.PRODUCT_FITTING_TYPE.Add(productFittingType);

                            var pfta = new PRODUCT_FITTING_TYPE_ASSET();
                            pfta.FITTING_TYPE_ASSET_ID = decimal.Parse(selectedAssetTypeID);
                            pfta.PRODUCT_ID = product.PRODUCT_ID;
                            pfta.PRODUCT_FITTING_TYPE_ASSET_ID = 0;
                            pfta.USER_ID = product.USER_ID;
                            db.PRODUCT_FITTING_TYPE_ASSET.Add(pfta);
                        }
                    }
                }

                #endregion
            }
            else
            {
                var pProdType = new PRODUCT_PRODUCT_TYPE();
                pProdType.PRODUCT_TYPE_ID = 2;
                pProdType.PRODUCT_ID = product.PRODUCT_ID;
                db.PRODUCT_PRODUCT_TYPE.Add(pProdType);
            }

            #region Try to save the IMAGE & PDF

            var ctr = 0;
            var imgChanged = false;
            var pdfChanged = false;

            foreach (var files in Request.Files)
            {
                var ticks = DateTime.Now.Ticks.ToString();

                HttpPostedFileBase file = Request.Files[ctr];
                if (file.ContentLength > 0)
                {
                    var pathString = "~/Content/User/";

                    if (file.ContentType.Contains("jp") | file.ContentType.Contains("png") | file.ContentType.Contains("gif"))
                    {
                        product.IMAGE = ticks + file.FileName;
                        pathString += "Images";
                        imgChanged = true;
                    }

                    if (file.ContentType.Contains("pdf"))
                    {
                        product.PDF = ticks + file.FileName;
                        pathString += "PDFs";
                        pdfChanged = true;
                    }

                    var savepath = Server.MapPath(Url.Content(pathString));
                    if (!Directory.Exists(savepath))
                        Directory.CreateDirectory(savepath);
                    var filePath = Path.Combine(@savepath, Path.GetFileName(ticks + file.FileName));
                    file.SaveAs(filePath);
                }
                ctr++;
            }

            if (!imgChanged)
            {
                // Go fetch the image
                product.IMAGE = String.IsNullOrEmpty(c_img) ? null : c_img;
            }

            if (!pdfChanged)
            {
                // Go fetch the PDF
                product.PDF = String.IsNullOrEmpty(c_pdf) ? null : c_pdf;
            }

            #endregion

            // Find the selected SUPPLIER
            var supplier = collection["Supplier"];
            product.SUPPLIER_ID = decimal.Parse(supplier);

            try
            {
                db.PRODUCTs.Add(product);
                db.SaveChanges();
                return RedirectToAction("Index", new { productType = ProductType });
            }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    }
                }

            }
            return View(product);
        }

        //
        // GET: /Component/Delete/5
 
        public ActionResult Delete(decimal id)
        {
            PRODUCT product = db.PRODUCTs.Find(id);
            return View(product);
        }

        //
        // POST: /Component/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(decimal id)
        {            
            PRODUCT product = db.PRODUCTs.Find(id);
            db.PRODUCTs.Remove(product);
            db.SaveChanges();
            return RedirectToAction("Index", new {productType = ProductType});
        }

        public List<FITTING_TYPE_ASSET> Fitting_Type_Assets { get; set; }
        /// <summary>
        /// Used to establish the fitting type ViewBags needed by various View Renderers
        /// </summary>
        private void EstablishFittingTypeViewBags()
        {
            //var fitting_type_assets = db.FITTING_TYPE_ASSET.Include(f => f.FITTING_TYPE).OrderBy(f => f.FITTING_TYPE.ORDER); // Old
            Fitting_Type_Assets = db.FITTING_TYPE_ASSET.Where(f => f.USER_ID == DATA.Custom_Classes.User.UserID).ToList();

            ViewBag.FittingTypes = GetFittingTypes() as List<FITTING_TYPE>;

            ViewBag.FittingTypeAssetList = Fitting_Type_Assets as IEnumerable<FITTING_TYPE_ASSET>;

            ViewBag.ProductFittingTypeAssets = db.PRODUCT_FITTING_TYPE_ASSET as IEnumerable<PRODUCT_FITTING_TYPE_ASSET>;
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}